﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;
using ProjectN.Core.Element;
using ProjectN.Core.Element.Def;
using ProjectN.Core.Fore;
using ProjectN.Core.Instance;

namespace ProjectN.GUI
{
    public partial class EditFrame : Form
    {
        private static readonly FrameInfo FRAME_INFO = new FrameInfo(0, 0, 0, 0);

        private PageInfo pageInfo;
        private PageRenderer renderer;
        private PageElementSelector selector;

        public EditFrame()
        {
            InitializeComponent();
        }

        public DynamicPage Page => this.PageInfo.Page;
        public required PageInfo PageInfo
        {
            get => pageInfo;
            set
            {
                this.pageInfo = value;

                FullRefresh();
            }
        }

        public String Status
        {
            get { return this.TsslSatus.Text; }
            private set { this.TsslSatus.Text = value; }
        }

        int _selectedElementId;
        public int SelectedElementId
        {
            get => _selectedElementId;
            set
            {
                _selectedElementId = value;
                if (_selectedElementId < 0)
                {
                    PropertyGrid.SelectedObject = this.Page;
                    BtnEditToTop.Enabled = false;
                    BtnEditToLast.Enabled = false;
                    BtnEditRemove.Enabled = false;
                }
                else
                {
                    PropertyGrid.SelectedObject = this.Page.GetElement(_selectedElementId);
                    BtnEditToTop.Enabled = true;
                    BtnEditToLast.Enabled = true;
                    BtnEditRemove.Enabled = true;
                }

            }
        }

        private void PictureRefresh()
        {
            this.renderer.Update();
            this.selector.Update();
            this.Invalidate();
        }

        private void FullRefresh()
        {
            this.TsslFileName.Text = PageInfo.Instance.Filename;
            this.TsslItemId.Text = Page.Identity;
            this.Text = string.Format(Properties.Resources.S_TITLE_FORMAT, Page.Identity);

            pageInfo.Page.Data = this.PageInfo.Instance.Data;

            this.renderer = new PageRenderer(Page,
                new Action<string>((string status) => { this.Status = status; }),
                new Action(() => { this.Refresh(); })
            );

            this.selector = new PageElementSelector(Page,
                new Action<string>((string status) => { this.Status = status; })
            );

            this.ImageDisplay.Image = this.renderer.Image;
            this.ImageDisplay.DisplaySize = this.renderer.Image.Size;
            this.ImageDisplay.FrameInfo = FRAME_INFO;
            this.ImageDisplay.Scaling = 1F;
        }

        private void TsmiAbout_Click(object sender, EventArgs e)
        {
            Form aboutBox = new Core.AboutBox();
            aboutBox.Owner = this;
            aboutBox.Show();
        }

        private void RtsmRefresh_Click(object sender, EventArgs e)
        {
            //this.renderer.Update();
            FullRefresh();
        }


        private void TsmiScalingOption_Click(object sender, EventArgs e)
        {
            this.GbScaling.Visible = !this.GbScaling.Visible;

        }

        private void TbScaling_ValueChanged(object sender, EventArgs e)
        {
            this.ImageDisplay.Scaling = this.TbScaling.Value / 100F;
            this.ImageDisplay.Refresh();
            this.LbScalingNum.Text = Convert.ToString(this.TbScaling.Value);
        }

        private void ImageDisplay_Click(object sender, EventArgs e)
        {
            Point clicked = ImageDisplay.CursorPositionOnImage;
            int elementId = selector.ClickedElementId(clicked);
            this.SelectedElementId = elementId;
        }

        private void TsmiOpenFile_Click(object sender, EventArgs e)
        {
            var result = OpenFileDialog.ShowDialog(this);
            if (result == DialogResult.OK)
            {
                try
                {
                    var instance = Creation.ReadFile(OpenFileDialog.FileName).Value;
                    this.PageInfo = new(instance, instance.MajorPage.Guid);
                }
                catch (Exception exception)
                {
                    this.CreateErrorInfoBox(exception, Properties.Resources.E_OPENFILE_FAILED_TITLE, Properties.Resources.E_OPENFILE_FAILED_MSG);
                }
            }
        }

        private void TsmiShowProperties_Click(object sender, EventArgs e)
        {
            var window = new PropertyEditForm()
            {
                Items = [this.Page],
                Title = "页面属性 - ProjectN"
            };
            window.Show(this);
        }

        private void PropertyGrid_SelectedObjectsChanged(object sender, EventArgs e)
        {
            NameBox.Text = PropertyGrid.SelectedObject?.ToString() ?? "无";
        }

        private void PropertyGrid_PropertyValueChanged(object s, PropertyValueChangedEventArgs e)
        {
            Page.Update();
            RtsmRefresh_Click(null, null);
        }

        private void TsmiSave_Click(object sender, EventArgs e)
        {
            var result = SaveFileDialog.ShowDialog(this);
            if (result == DialogResult.OK)
            {
                try
                {
                    this.PageInfo.Instance.SaveToFile(SaveFileDialog.FileName);
                }
                catch (Exception exception)
                {
                    this.CreateErrorInfoBox(exception, "保存页面失败", "保存页面文件失败，可能是路径有误或文件正在使用。");
                }
            }
        }

        private void EditFrame_Load(object sender, EventArgs e)
        {
            this.SelectedElementId = -1;
            this.CbEditNew.Items.AddRange(types.Keys.ToArray());
        }

        private void BtnEditToLast_Click(object sender, EventArgs e)
        {
            Page.Elements.SetFirst(this.SelectedElementId);
            this.PictureRefresh();
        }

        private void BtnEditToTop_Click(object sender, EventArgs e)
        {
            Page.Elements.SetLast(this.SelectedElementId);
            this.PictureRefresh();
        }

        private void BtnEditRemove_Click(object sender, EventArgs e)
        {
            Page.Elements.Remove(this.SelectedElementId);
            this.PictureRefresh();
        }

        private static Dictionary<string, Func<IElement>> types = new Dictionary<string, Func<IElement>>
        {
            {"线段", () => new Line() { Pen = new (), P1 = new(), P2 = new() } },
            {"长方形", () => new Core.Element.Rectangle { Fill = new(), Pen = new(), Rect = new()} },
            {"文本", () => new RectedText { Context = "", Brush = new(), Position = new(), BorderWidth = 1, Font = FontInfo.Default } },
            {"贝塞尔曲线", () => new Bezier { P1 = new(), P2 = new(), P3 = new(), P4 = new(), Pen = new() } },
        };

        private void BtnEditNew_Click(object sender, EventArgs e)
        {
            var c = types[CbEditNew.Text];
            var id = Page.Elements.Add(c());
            SelectedElementId = id;
            PictureRefresh();
        }
        private void TsmiNewFile_Click(object sender, EventArgs e)
        {
            PageInfo = Creation.CreateEmpty(100, 100, "空", Color.White).Value.GetMajorInfo();
            SelectedElementId = -1;
            FullRefresh();
        }

        public static EditFrame CreateEmpty()
        {
            var info = Creation.CreateEmpty(100, 100, "空", Color.White).Value.GetMajorInfo();
            return new EditFrame { PageInfo = info };
        }
    }
}
